home *** CD-ROM | disk | FTP | other *** search
- #define DISABLE_LOCAL_CALLTRACE 1 // Set to 1 to disable Call Traces for this file.
- #define DISABLE_LOCAL_DEBUG 0 // Set to 1 to disable all debugging for this file.
- #include "DebugUtils.h"
-
- #include <Errors.h>
- #include <Gestalt.h>
- #include "ContextUtils.h"
- #include "DesktopDoubler.h"
- #include "Nub.h"
- #include "PatchHarness.h"
- #include "ProcInfo.h"
- #include "Version.h"
-
-
-
-
-
- #ifdef __cplusplus
- extern "C" {
- #endif
-
- extern void __InitCode__(void);
- extern void __destroy_global_chain(void);
-
- #if APPBUILD
- OSStatus NubMain(Handle code);
- #else
- pascal OSStatus main(Handle code);
- #endif
-
- static OSStatus LoadNub(Handle code);
- static pascal OSStatus UnloadNub(Handle *code);
- static Boolean isPressed(UInt8 keyCode);
-
- #if GENERATING68K && !GENERATINGCFM && __A5__
- void RememberA5(void);
- #endif
-
- #ifdef __cplusplus
- }
- #endif
-
-
-
-
-
- #if GENERATINGPOWERPC
- ProcInfoType __procinfo = uppNubLoadProcInfo;
- static RoutineDescriptor gUnloadNubRD = BUILD_ROUTINE_DESCRIPTOR(uppNubUnloadProcInfo,UnloadNub);
- static RoutineDescriptor *gUnloadNubUPP = (RoutineDescriptor*)&gUnloadNubRD;
- #else
- static NubUnloadUPP gUnloadNubUPP = UnloadNub;
- #endif
-
-
- NubInfo *gInfo = NULL;
- static Handle gCode = NULL;
- static UInt32 gAbortLoad = 0;
- static Boolean gBootInstall = false;
- static Boolean gDestructOnUnload = false;
-
-
-
-
-
- #if APPBUILD
- OSStatus NubMain(Handle code)
- #pragma mark NubMain
- #else
- pascal OSStatus main(Handle code)
- #endif
- {
- #if !APPBUILD
- GlobalContext globals;
- #endif
- OSStatus err;
-
-
- #if DEBUG
- // Check for CapsLock.
- if (isPressed(0x39))
- {
- DebugStr("\pNub abort checkpoint");
- if (gAbortLoad)
- {
- dprintf(kDConPrefix "LoadNub aborted\n");
- return -1;
- }
- }
- #endif
-
- // Save application global A5 world.
- #if GENERATING68K && !GENERATINGCFM && __A5__
- RememberA5();
- #endif
-
- // 68K code resources need to construct their own static C++ data objects (A4 must be
- // setup). We only need to do this for 68K because it'll be automagically constructed
- // by the CFM init routine for a PowerPC code resource.
- #if !GENERATINGPOWERPC && !APPBUILD
- __InitCode__();
- #endif
-
- // Install the Nub, if this fails we just forward the error.
- // Our caller has already detached us and if we return an error it
- // is responsible for unloading us, otherwise we will stick around.
- err = LoadNub(code);
- if (err != noErr)
- {
- dprintf(kDConPrefix "LoadNub failed: %ld\n",err);
- // Code resources need to destruct their own static C++ data objects (A4 must be
- // setup for 68K). We must do this PowerPC code resources too, as CFM termination
- // routines won't be invoked when a code resource is unloaded.
- #if !APPBUILD
- __destroy_global_chain();
- #endif
- }
- else
- gDestructOnUnload = true;
-
- return err;
- }
-
-
-
-
-
- OSStatus LoadNub(Handle code)
- {
- THzContext zone(SystemZone());
- NubInfo *info;
- SInt32 result;
- OSStatus err;
-
-
- // Check Gestalt to determine install/reinstall.
- err = Gestalt(kNubSelector,(SInt32*)&info);
- if (err != noErr)
- info = NULL;
-
- // The INIT must be loaded first to bootstrap the debugging application version,
- // otherwise we won't be able to install any patches.
- #if APPBUILD
- if ((err != noErr) || (info == NULL))
- return notOpenErr;
- #endif
-
- // Check for Nub already being present and loaded.
- if ((err == noErr) && info && (info->signature == kNubSignature))
- return opWrErr;
-
- // If the Gestalt selector didn't exist, or the permanent data structures haven't
- // been setup (which means we haven't patched anything yet), this is an install.
- if ((err != noErr) || (info == NULL))
- {
- if (info == NULL)
- {
- // Allocate system exposed permanent data structures.
- info = (NubInfo*)NewPtrSysClear(sizeof(NubInfo));
- if (info == NULL)
- {
- err = MemError();
- dprintf(kDConPrefix "Couldn't allocate NubInfo: %ld\n",err);
- return err;
- }
- }
-
- if (err != noErr)
- {
- // Install system wide patch harness.
- err = InstallPatchHarness(&info->patchList);
- if (err != noErr)
- {
- dprintf(kDConPrefix "InstallPatchHarness failed: %ld\n",err);
- DisposePtr((Ptr)info);
- return err;
- }
- }
-
- // Setup pointer to NubInfo as Gestalt selector result.
- err = InstallPatch(info->patchList,'GSEL',(UniversalProcPtr)info);
- if (err != noErr)
- {
- dprintf(kDConPrefix "Couldn't install '.4%s' Gestalt selector: %ld\n",err);
- DisposePtr((Ptr)info);
- return err;
- }
-
- // Set boot time flag.
- gBootInstall = true;
- }
-
- // Setup globals.
- gCode = code;
- gInfo = info;
-
- // Setup NubInfo record.
- gInfo->signature = kNubSignature;
- *(UInt32*)&gInfo->version = kNubVersion;
- *(UInt32*)&gInfo->compatible = kNubCompatible;
- gInfo->unloadProc = gUnloadNubUPP;
-
- // Make it go....
- err = InitDesktopDoubler();
- if (err != noErr)
- {
- dprintf(kDConPrefix,"InitDesktopDoubler failed: %ld\n",err);
- UnloadNub(&gCode);
- return err;
- }
-
- #if DEBUG
- {
- UInt32 vers = kNubVersion;
- char text[32];
-
- dprintf(kDConPrefix "DesktopDoubler %s installed\n",NumVersionToCString(text,(NumVersion*)&vers));
- }
- #endif
-
- return noErr;
- }
-
-
-
-
-
- pascal OSStatus UnloadNub(Handle *code)
- {
- GlobalContext globals;
- THzContext zone(SystemZone());
- PatchDesc *patch;
-
-
- // Make it stop...
- TermDesktopDoubler();
-
- // Remove all patches.
- patch = gInfo->patchList;
- while(patch != NULL)
- {
- // Don't remove our special GestaltSelector patch.
- if ((patch->type != 'GSEL') && patch->remove)
- CallPatchRemoveProc(patch->remove,patch);
-
- patch = patch->next;
- }
-
- // Clear NubInfo record.
- gInfo->signature = 0;
- gInfo->unloadProc = NULL;
-
- // Caller must dispose.
- #if APPBUILD
- *code = NULL;
- #else
- *code = gCode;
- #endif
-
- if (gDestructOnUnload)
- {
- // Code resources need to destruct their own static C++ data objects (A4 must be
- // setup for 68K). We must do this PowerPC code resources too, as CFM termination
- // routines won't be invoked when a code resource is unloaded.
- #if !APPBUILD
- __destroy_global_chain();
- #endif
- gDestructOnUnload = false;
- }
-
- return noErr;
- }
-
-
-
-
-
- Boolean isPressed(UInt8 keyCode)
- {
- UInt8 km[16];
-
-
- GetKeys((SInt32*)&km[0]);
- return ((km[keyCode >> 3] >> (keyCode & 7)) & 1);
- }
-
-
-
-
-
- #if GENERATING68K && !GENERATINGCFM && __A5__
- asm void RememberA5(void)
- {
- LEA @A5Storage,A0
- MOVE.L A5,(A0)
- RTS
-
- entry GetCurrentA5
- MOVE.L @A5Storage,D0
- RTS
-
- @A5Storage:
- DC.L 0x00000000
- }
- #endif
-